package com.cll.learn.rpc.common.coder;

import com.cll.learn.rpc.common.serializer.Serializable;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

/**
 * 描述信息:
 * 自定义的解码器
 * 根据对应的编码规则进行解码
 * 入站操作，将二进制信息转换为对象类型
 * @author CLL
 * @version 1.0
 * @date 2020/9/14 15:31
 */
@RequiredArgsConstructor
public class RpcDecoder extends ByteToMessageDecoder {

    private static final Logger logger = LoggerFactory.getLogger(RpcDecoder.class);

    private static final int BYTE_DATA_HEADER_LENGTH = 1 << 2;

    /**
     * 反序列化对象的类型
     */
    @NonNull
    private Class<?> clazz;

    /**
     * 反序列化方式
     */
    @NonNull
    private Serializable serializable;

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        logger.info("===>>> decode");
        int readableBytes = in.readableBytes();
        if (readableBytes < RpcDecoder.BYTE_DATA_HEADER_LENGTH) {
            logger.error("****** 数据编码错误，无法解析");
            return;
        }
        // 放置数据错误，进行数据的恢复
        in.markReaderIndex();
        int dataLengthInHeader = in.readInt();

        if (dataLengthInHeader != in.readableBytes()) {
            logger.error("****** 消息头中定义的消息长度和接收到的数据长度不一致");
            return;
        }

        byte[] byteData = new byte[dataLengthInHeader];
        in.readBytes(byteData);

        Object object = serializable.deserializable(this.clazz, byteData);
        out.add(object);
    }
}
